/**
 * 
 */
package com.orcwar.engine;

import static com.orcwar.engine.OWConstants.TILE_SIZE;
import android.graphics.RectF;

import com.orcwar.enums.DirectionEnum;
import com.orcwar.enums.OWTileType;

/**
 * @author Callil
 * 
 */
public class OWTile {

	/** The id of the tile. */
	private int id;
	
	/** The position of the tile. */
	private RectF position = new RectF();

	/** The type of the tile. */
	private OWTileType tileType;

	/** The unit currently present on this tile. */
	private OWUnit unit;
	
	/** The cost of movements deduced when walking on this tile. */
	private int cost = 1;
	
	// Draw attributes
	private String idStr;

	/**
	 * x position in the map (column)
	 */
	private int x;

	/**
	 * y position in the map (row)
	 */
	private int y;

	/**
	 * Tag of the composanteConnexe the tile is in.
	 */
	private int tag;

	/**
	 * Constructor.
	 * @param id the id of the tile
	 * @param x the x position on the map
	 * @param y the y position on the map
	 */
	public OWTile(int id, int x, int y) {
		this.id = id;
		this.x = x;
		this.y = y;
		this.idStr = String.valueOf(id);
		
		// set the position
		computePosition();
	}
	
	
	
	/**
	 * Copy constructor.
	 * @param tile
	 */
	public OWTile(OWTile tile) {
		super();
		if (tile != null) {
			this.id = tile.id;
			this.position = tile.position;
			this.tileType = tile.tileType;
			this.unit = tile.unit;
			this.cost = tile.cost;
			this.idStr = tile.idStr;
			this.x = tile.x;
			this.y = tile.y;
			this.tag = tile.tag;
		}
	}




	//*******************//
	//HASHCODE AND EQUALS//
	
	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		OWTile other = (OWTile) obj;
		if (id != other.id)
			return false;
		return true;
	}
	
	//HASHCODE AND EQUALS//
	//*******************//
	
	
	/**
	 * Return the orientation of tile2 compared to "this". For exemple, if "this"
	 * is on the left of tile2, it will return DirectionEnum.RIGHT.
	 * 
	 * @param tile2
	 *            the tile to locate
	 * @return a DirectionEnum
	 */
	public DirectionEnum directionToTile(OWTile tile2) {
		if (this.getX() == tile2.getX()) {
			return this.getY() > tile2.getY() ? DirectionEnum.UP
					: DirectionEnum.DOWN;
		} else if (this.getY() == tile2.getY()) {
			return this.getX() > tile2.getX() ? DirectionEnum.LEFT
					: DirectionEnum.RIGHT;
		} else {
			if (this.getX() < tile2.getX()) {
				return this.getY() > tile2.getY() ? DirectionEnum.UP_RIGHT 
						: DirectionEnum.DOWN_RIGHT;
			} else {
				return this.getY() > tile2.getY() ? DirectionEnum.UP_LEFT
						: DirectionEnum.DOWN_LEFT;
			}
		}
	}
	
	/**
	 * Compute the position of the tile based on the x and y.
	 */
	private void computePosition() {
		// set the position
		position.set(x * TILE_SIZE, y * TILE_SIZE, x * TILE_SIZE + TILE_SIZE, y
				* TILE_SIZE + TILE_SIZE);
	}
	
	public RectF getPosition() {
		return position;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
		computePosition();
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
		computePosition();
	}

	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(int id) {
		this.id = id;
	}

	
	
	/**
	 * @return the idStr
	 */
	public String getIdStr() {
		return idStr;
	}


	/**
	 * @param idStr the idStr to set
	 */
	public void setIdStr(String idStr) {
		this.idStr = idStr;
	}


	/**
	 * @return the blockingMovement
	 */
	public boolean allowsMovement() {
		return tileType.allowsMovement();
	}

	/**
	 * @return the blockingAttacks
	 */
	public boolean allowsAttacks() {
		return tileType.allowsAttacks();
	}

	public OWTileType getTileType() {
		return tileType;
	}

	public void setTileType(OWTileType tileType) {
		this.tileType = tileType;
	}

	/**
	 * @return the currentUnit
	 */
	public OWUnit getCurrentUnit() {
		return unit;
	}

	
	/**
	 * @param currentUnit
	 *            the currentUnit to set
	 */
	public void setCurrentUnit(OWUnit currentUnit) {
		setCurrentUnit(currentUnit, true);
	}
	
	/**
	 * @param currentUnit
	 *            the currentUnit to set
	 */
	public void setCurrentUnit(OWUnit currentUnit, boolean updatePosition) {
		this.unit = currentUnit;
		if (unit != null) {
			if (updatePosition) {
				this.unit.setPosition(new RectF(this.getPosition()));
			}
			this.unit.setTile(this);
		}
	}

	
	public boolean canGoThrough() {
		//True if the tile is GROUND and doesn't contain a unit
		return tileType.allowsMovement() && this.unit == null;
	}
	
	public boolean canGoThrough(OWUnit unit) {
		//True if the tile is GROUND and doesn't contain a unit different
		//than the one in parameter
		return tileType.allowsMovement()
				&& (unit == null || this.unit == null || this.unit.getId() == unit.getId());
	}

	public String toString() {
		return "[" + id + tileType.getSmallName() + "]";
	}

	public int getTag() {
		return tag;
	}

	public void setTag(int tag) {
		this.tag = tag;
	}

	/**
	 * @return the cost
	 */
	public int getCost() {
		return cost;
	}

	/**
	 * @param cost the cost to set
	 */
	public void setCost(int cost) {
		this.cost = cost;
	}

}
